<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>Untitled Document</title>
		<script type=text/javascript charset=utf-8>
				// 实现接口的第三种方式：鸭式辨型法实现接口(最完美的javascript实现接口方式)
				// 注解描述法、属性检测法
				// 鸭式辨型法实现的核心：一个类实现接口的主要目的：把接口里的方法都实现（检测方法）
				// 完全面向对象 代码也实现统一  也解耦了
				
				// 一： 接口类 Class Interface ==>实例化N多个接口
				
				/**
				 * 接口类需要2个参数
				 * 参数1: 接口的名字 (string)
				 * 参数2: 接受方法名称的集合(数组) (array)
				 */
				var Interface = function(name,methods){
					//判断接口的参数个数
					if(arguments.length != 2){
						throw new Error('this instance interface constructor arguments must be 2 length!');
					}
					this.name = name ; 
					this.methods = [] ; //定义一个内置的空数组对象 等待接受methods里的元素(方法名字)
					for(var i = 0,len = methods.length ; i <len ; i++){
						 if( typeof methods[i] !== 'string'){
						 		throw new Error('the Interface method name is error!');
						 }
						 this.methods.push(methods[i]);
					}
				}
				

				
				// 二： 准备工作：
				
				// 1 实例化接口对象
				var CompositeInterface = new Interface('CompositeInterface' , ['add' , 'remove']);
				var FormItemInterface  = new Interface('FormItemInterface' , ['update','select']);
			
				//  CompositeImpl implements CompositeInterface , FormItemInterface
				
				// 2 具体的实现类 
				var CompositeImpl = function(){
					
				} 
				
				// 3 实现接口的方法implements methods 			
				CompositeImpl.prototype.add = function(obj){
					alert('add');
					// do something ...
				}
				CompositeImpl.prototype.remove = function(obj){
					alert('remove');
					// do something ...
				}			
				CompositeImpl.prototype.update = function(obj){
					alert('update');
					// do something ...
				}	
				/*			
				CompositeImpl.prototype.select = function(obj){
					alert('select');
					// do something ...
				}	
				*/
				
				// 三：检验接口里的方法
				// 如果检验通过 不做任何操作 不通过：浏览器抛出error
				// 这个方法的目的 就是检测方法的
				Interface.ensureImplements = function(object){
					// 如果检测方法接受的参数小于2个 参数传递失败!
					if(arguments.length < 2 ){
						throw new Error('Interface.ensureImplements method constructor arguments must be  >= 2!');
					}
					
					// 获得接口实例对象 
					for(var i = 1 , len = arguments.length; i<len; i++ ){
						var instanceInterface = arguments[i];
						// 判断参数是否是接口类的类型
						if(instanceInterface.constructor !== Interface){
							throw new Error('the arguments constructor not be Interface Class');
						}
						// 循环接口实例对象里面的每一个方法
						for(var j = 0 ; j < instanceInterface.methods.length; j++){
							// 用一个临时变量 接受每一个方法的名字(注意是字符串)
							var methodName = instanceInterface.methods[j];
							// object[key] 就是方法
							if( !object[methodName] || typeof object[methodName] !== 'function' ){
								throw new Error("the method name '" + methodName + "' is not found !");
							}
						}
					}
				}
				
				var c1 = new CompositeImpl();
				Interface.ensureImplements(c1,CompositeInterface,FormItemInterface);
				c1.add();
					
			
			
		</script>
	</head>
	<body>
	</body>
</html>
